home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Pascal / Libraries / MCC Utils / MCHandlesAndStrs.p < prev    next >
Encoding:
Text File  |  1994-05-04  |  23.4 KB  |  795 lines  |  [TEXT/PJMM]

  1. {This document is formated in monaco 9 pt                                          }
  2. {                                                                                  }
  3. {LEGAL STUFF                                                                       }
  4. {                                                                                  }
  5. {Copyright © 1994 by University of Melbourne. All Rights Reserved. This work is    }
  6. {provided "as is" and without any express or implied warranties, including,        }
  7. {without limitation, the implied warranties of merchantability and fitness         }
  8. {for a particular purpose.                                                         }
  9. {                                                                                  }
  10. {University of Melbourne is not responsible for the consequences of the use of this}
  11. {work, regardless of the cause. You may use this work in a public domain,          }
  12. {freeware, or shareware product with no restrictions, as long as you include       }
  13. {the following notice in your product's about box or splash screen:                }
  14. {  "Portions Copyright © 1994 by University of Melbourne".                         }
  15. {If you use more than 50 lines of this work, please credit the author also:        }
  16. {  "Portions by Michael Cutter"                                                    }
  17. {Public domain is defined as something that you release to the public, without     }
  18. {copyright and without restrictions on use. Freeware is a copyrighted work,        }
  19. {for which you charge no money. Shareware is a copyrighted work for which you      }
  20. {charge a fee if the user decides to keep it. If you intend to use this work       }
  21. {in a commercial product, please contact us.                                       }
  22. {                                                                                  }
  23. {                                                                                  }
  24. {OTHER STUFF                                                                       }
  25. {                                                                                  }
  26. {AUTHOR:                                                                           }
  27. { Michael Trevor Cutter                                                            }
  28. {                                                                                  }
  29. {CONTACT:                                                                          }
  30. {  Internet:                                                                       }
  31. {    mtc@arbld.unimelb.edu.au (Preferred)                                          }
  32. {  Snail Mail:                                                                     }
  33. {    Dept of Architecture & Building                                               }
  34. {    University of Melbourne                                                       }
  35. {    Parkville VIC 3052                                                            }
  36. {    AUSTRALIA                                                                     }
  37. {                                                                                  }
  38. {PERSONAL STUFF                                                                    }
  39. {  I'd really appreciate it if you'd let me know what you're using my code         }
  40. {  in, (send me email or a postcard). Please report any bugs or errors to me.      }
  41. {                                                                                  }
  42. {MODULE DESCRIPTION                                                                }
  43. {This is a collection of functions which provide various                           }
  44. {facilities for processing handles and pascal strings, and                         }
  45. {converting between one form and another.                                          }
  46. {Like all my code, it is probably not perfect, but any                             }
  47. {bugs you find , please report them to me , so that I can                          }
  48. {fix them!                                                                         }
  49. {Note some of this stuff is ancient and highly embarrassing...                     }
  50.  
  51. unit MCHandlesAndStrs;
  52.  
  53. interface
  54.  
  55. {Sets the length of the string.}
  56.     procedure MCSetStrLen (var str: Str255;
  57.                                     len: longint);
  58.  
  59. {Returns the first 255 chars (or less) of the handle in the str}
  60.     procedure MCHndlToStr (thehndl: Handle;
  61.                                     var str: Str255);
  62. {Counts the number of $0D delimited lines in a handle}
  63. {NOTE: it provides the number of visible lines, NOT the number of returns in the handle}
  64. {So if the first char is a return, it is ignored, and if the last char is not a return,}
  65. {then it is also part of a line, etc.}
  66.     function MCCountLinesInHndl (thehndl: Handle): longint;
  67. {Returns line X from thehndl, and return it as a handle}
  68.     function MCGetHndlLineXFromHndl (thehndl: handle;
  69.                                     linex: longint): Handle;
  70. {Returns the next line after offset from the handle as a handle}
  71.     function MCGetNextHndlLineFromHndl (thehndl: handle;
  72.                                     var offset: longint): Handle;
  73. {Returns the next item after offset as delimited by delim as a handle}
  74.     function MCGetNextHndlItemFromHndl (thehndl: handle;
  75.                                     delim: char;
  76.                                     var offset: longint): Handle;
  77. {Returns line X from the handle as a string}
  78.     function MCGetStrLineXFromHndl (thehndl: handle;
  79.                                     linex: longint): str255;
  80. {Returns the next line after offset from the handle as a string}
  81.     function MCGetNextStrLineFromHndl (thehndl: handle;
  82.                                     var offset: longint): Str255;
  83. {Count the number of items in a string, as delimited by the char}
  84.     function MCGetNumberOfItemsInStr (thestr: str255;
  85.                                     delimiter: char): integer;
  86. {Returns item X from the string as delimited by the char as a string}
  87.     function MCGetStrItemXFromStr (thestr: Str255;
  88.                                     itemx: integer;
  89.                                     delimiter: char): str255;
  90. {Returns item X from the handle as delimited by the char as a string}
  91.     function MCGetStrItemXFromHndl (thehndl: Handle;
  92.                                     itemx: longint;
  93.                                     delimiter: char): str255;
  94. {Returns the everything between offset and the next delimiter as a string}
  95.     function MCGetStrItemOffsetFromHndl (thehndl: Handle;
  96.                                     delim: char;
  97.                                     var offset: longint {offset to copy from}
  98.                                     ): Str255;
  99. {Appends the given string to the handle (if handle is nil, allocates a new handle)}
  100.     function MCAppendStrToHndl (str: Str255;
  101.                                     var h: Handle): OSErr;
  102. {Appends the contents of the pointer to the handle}
  103.     function MCAppendPtrToHndl (p: Ptr;
  104.                                     len: longint;
  105.                                     var h: Handle): OSErr;
  106. {Appends a return character to the handle}
  107.     function MCAppendReturnToHndl (var h: Handle): OSErr;
  108. {Appends the fromh handle onto the toh handle}
  109.     function MCAppendHndlToHndl (fromh: handle;
  110.                                     var toh: handle): OSErr;
  111. {Converts a pascal string to a null-terminated string without using HyperXCMD.lib}
  112.     function MCHPascalToZero (str: Str255): Handle;
  113. {Converts a null-terminated string to a pascal string without using HyperXCMD.lib}
  114.     function MCHZeroToPascal (strhdl: Handle): str255;
  115. {Counts the number of lines in a null-terminated string}
  116.     function MCNumberOfLinesInZero (thestr: handle): integer;
  117. {Returns line X from null-terminated string as a pascal string}
  118.     function MCGetStrLineXFromZero (lineno: integer;
  119.                                     thehndl: handle): str255;
  120.  
  121. implementation
  122.  
  123.     procedure MCSetStrLen (var str: Str255;
  124.                                     len: longint);
  125.     begin
  126.         if len > 255 then
  127.             len := 255
  128.         else if len < 0 then
  129.             len := 0;
  130.         str[0] := chr(len);
  131.     end;
  132.  
  133.     procedure MCHndlToStr (thehndl: Handle;
  134.                                     var str: Str255);
  135.         var
  136.             hndllen: longint;
  137.     begin
  138.         if thehndl = nil then
  139.             begin
  140.                 DebugStr('nil handle in MCHndlToStr');
  141.                 str := '';
  142.             end
  143.         else
  144.             begin
  145.                 str := '';
  146.                 hndllen := GetHandleSize(thehndl);
  147.                 if hndllen > 255 then
  148.                     hndllen := 255;
  149.                 BlockMove(thehndl^, @str[1], hndllen);
  150.                 MCSetStrLen(str, hndllen);
  151.             end;
  152.     end;
  153.  
  154.     function MCCountLinesInHndl (thehndl: Handle): longint;
  155.         var
  156.             count: longint;
  157.             returnstr: Str32;
  158.             offset, lastoffset: longint;
  159.     begin
  160.         count := 0;
  161.         if thehndl <> nil then
  162.             begin
  163.                 returnstr := chr($0D); {store return in str}
  164.                 offset := 0;
  165.                 offset := Munger(thehndl, offset, @returnstr[1], 1, nil, 0); {get the first return}
  166.                 lastoffset := offset;
  167.                 while offset > 0 do {because if the first one is a return, it's not really a line}
  168.                     begin
  169.                         count := count + 1;
  170.                         offset := offset + 1;{to avoid finding the same return}
  171.                         offset := Munger(thehndl, offset, @returnstr[1], 1, nil, 0); {get the next return}
  172.                         if offset > 0 then
  173.                             lastoffset := offset; {and remember it if we found one}
  174.                     end;
  175.                 if lastoffset <> GetHandleSize(thehndl) then
  176.                     begin {if the last char is not a return, then there must be one more line}
  177.                         count := count + 1;
  178.                     end;
  179.             end;
  180.         MCCountLinesInHndl := count;
  181.     end;
  182.  
  183.     function MCOldCountLinesInHndl (thehndl: Handle): longint;
  184. {returns the number of return delimited lines in the handle pointed to by thehndl}
  185.         var
  186.             b: boolean;
  187.             n: longint;
  188.             p: ptr;
  189.             count: longint;
  190.             handsize: longint;
  191.     begin
  192. {intialize}
  193.         if thehndl = nil then
  194.             MCOldCountLinesInHndl := 0
  195.         else
  196.             begin
  197.                 handsize := GetHandleSize(thehndl) - 1;{remember to take out EOF if from a file!}
  198.                 if handsize > -1 then
  199.                     begin
  200.                         p := nil;
  201.                         n := 0;
  202.                         count := 0;
  203.                         while n < handsize do
  204.                             begin
  205.                                 p := pointer(ord4(thehndl^) + n);
  206.                                 n := n + 1;
  207.                                 if (p^ = $0D) then
  208.                              {$0D is return}
  209.                                     count := count + 1;
  210.                             end;
  211.                         if (p^ <> $0D) then
  212.                             MCOldCountLinesInHndl := count + 1 {for the last line, wot doesn't end with a return}
  213.                         else
  214.                             MCOldCountLinesInHndl := count;
  215.                     end
  216.                 else
  217.                     MCOldCountLinesInHndl := 0;{because no returns either!}
  218.             end;
  219.     end;
  220.  
  221.     function MCGetHndlLineXFromHndl;
  222. {this function returns a handle containing the specified line in thehndl}
  223.         var
  224.             b: boolean;
  225.             n, count: longint;
  226.             p, q: ptr;
  227.             finalhandle: Handle;
  228.             c: char;
  229.             err: OSErr;
  230.             l: integer;
  231.             handsize: longint;
  232.     begin
  233. {move pointer to start of line x of string}
  234.         handsize := GetHandleSize(thehndl) - 2;{- 2 because positions go from 0-49 if hs = 50, and pos 49 = EOF!!!}
  235.         finalhandle := NewHandle(0);
  236.         b := true;
  237.         p := nil;
  238.         n := 0;
  239.         count := 0;
  240.         while b and (n <= handsize - 2) do
  241.             begin
  242.                 p := pointer(ord4(thehndl^) + n);
  243.                 n := n + 1;
  244.                 if count = linex - 1 then
  245.                     b := false;
  246.                 if (p^ = $0D) then
  247.                     count := count + 1;
  248.                 if p^ = 0 then
  249.                     b := false;
  250.             end;
  251.  
  252. {copy until hit another return or a zero into a string}
  253.         if (p^ <> 0) and (n <= handsize) then
  254.             begin
  255.                 b := true;
  256.                 l := 0;
  257.                 while b do
  258.                     begin
  259.                         if (p^ = $0D) or (p^ = 0) then
  260.                             b := false
  261.                         else
  262.                             begin
  263.                                 c := chr(p^);
  264.                                 l := l + 1;
  265.                                 err := ptrAndHand(p, finalhandle, 1);
  266.                             end;
  267.                         p := pointer(ord4(thehndl^) + n);
  268.                         n := n + 1;
  269.                     end;
  270.                 MCGetHndlLineXFromHndl := finalHandle;
  271.             end;
  272.     end;
  273.  
  274.     function MCGetNextHndlLineFromHndl;
  275. {starts looking from an offset passed to the function, which then contains where the}
  276. {search left off last time}
  277. {to search sequentially along a handle from start, pass 0 as the initial value for offset, and }
  278. {keep calling with same value in a loop}
  279. {should really rewrite some of these functions using BlockMove. Have to find out how to do it!}
  280.         var
  281.             b: boolean;
  282.             count: longint;
  283.             p, q: ptr;
  284.             finalhandle: Handle;
  285.             c: char;
  286.             err: OSErr;
  287.             l: integer;
  288.             handsize: longint;
  289.     begin
  290. {move pointer to start of line x of string}
  291.         handsize := GetHandleSize(thehndl) - 1;{remember to crop off the EOF if reading from a file}
  292.         finalhandle := NewHandle(0);
  293.         b := true;
  294.         p := nil;
  295.  
  296.         p := pointer(ord4(thehndl^) + offset);
  297.         offset := offset + 1;
  298.  
  299. {copy until hit another return or a zero into a string}
  300.         if (p^ <> 0) and (offset <= handsize) then
  301.             begin
  302.                 b := true;
  303.                 l := 0;
  304.                 while b do
  305.                     begin
  306.                         if (p^ = $0D) or (p^ = 0) then
  307.                             b := false
  308.                         else
  309.                             begin
  310.                                 c := chr(p^);
  311.                                 err := ptrAndHand(p, finalhandle, 1);
  312.                             end;
  313.                         p := pointer(ord4(thehndl^) + offset);
  314.                         offset := offset + 1;
  315.                     end;
  316.                 offset := offset - 1;
  317.                 MCGetNextHndlLineFromHndl := finalHandle;
  318.             end
  319.         else if offset = handsize then
  320.             MCGetNextHndlLineFromHndl := nil;
  321.     end;
  322.  
  323.     function MCGetNextHndlItemFromHndl (thehndl: handle;
  324.                                     delim: char;
  325.                                     var offset: longint): Handle;
  326. {starts looking from an offset passed to the function, which then contains where the}
  327. {search left off last time}
  328. {to search sequentially along a handle from start, pass 0 as the initial value for offset, and }
  329. {keep calling with same value in a loop}
  330. {should really rewrite some of these functions using BlockMove. Have to find out how to do it!}
  331.         var
  332.             b: boolean;
  333.             count: longint;
  334.             p, q: ptr;
  335.             finalhandle: Handle;
  336.             c: char;
  337.             err: OSErr;
  338.             l: integer;
  339.             handsize: longint;
  340.     begin
  341. {move pointer to start of line x of string}
  342.         handsize := GetHandleSize(thehndl) - 1;    {remember to crop off the EOF if reading from a file}
  343.         finalhandle := NewHandle(0);
  344.         b := true;
  345.         p := nil;
  346.  
  347.         p := pointer(ord4(thehndl^) + offset);
  348.         offset := offset + 1;
  349.  
  350. {copy until hit another return or a zero into a string}
  351.         if (p^ <> 0) and (offset <= handsize) then
  352.             begin
  353.                 b := true;
  354.                 l := 0;
  355.                 while b do
  356.                     begin
  357.                         if (p^ = ord(delim)) or (p^ = 0) then
  358.                             b := false
  359.                         else
  360.                             begin
  361.                                 c := chr(p^);
  362.                                 err := ptrAndHand(p, finalhandle, 1);
  363.                             end;
  364.                         p := pointer(ord4(thehndl^) + offset);
  365.                         offset := offset + 1;
  366.                     end;
  367.                 offset := offset - 1;
  368.                 MCGetNextHndlItemFromHndl := finalHandle;
  369.             end
  370.         else if offset = handsize then
  371.             MCGetNextHndlItemFromHndl := nil;
  372.     end;
  373.  
  374.     function MCGetStrLineXFromHndl;
  375. {finds the requested line number, and returns the contents of that line, with no return attached}
  376. {NOTE - no longer trims the EOF character, cause it isn't always there, bimbo!}
  377.         var
  378.             b: boolean;
  379.             n, count, offset: longint;
  380.             p: ptr;
  381.             thestr: str255;
  382.             c: char;
  383.             err: OSErr;
  384.             l: longint;
  385.             handsize: longint;
  386.             retstr: str255;
  387.     begin
  388. {find offset of line number requested}
  389.         count := 0;
  390.         retstr := chr(13);
  391.         offset := -1;
  392.         while count < linex - 1 do
  393.             begin
  394.                 offset := offset + 1;
  395.                 offset := Munger(thehndl, offset, @retstr[1], 1, nil, 0); {find next return}
  396.                 if offset < 0 then {return not found, line number does not exist}
  397.                     begin
  398.                         MCGetStrLineXFromHndl := '';
  399.                         exit(MCGetStrLineXFromHndl);
  400.                     end
  401.                 else
  402.                     count := count + 1;
  403.             end;
  404.  
  405.         n := offset + 1;
  406.         p := Pointer(ord4(thehndl^) + n); {point p at the next character after the found return}
  407.  
  408. {copy what p points to until we hit the next return, or we go over the end of the handle}
  409.         handsize := GetHandleSize(thehndl) - 1; {because the offsets start at 0}
  410.         thestr := ''; {in case no more chars after this return}
  411.  
  412.         if (p^ <> 0) and (n <= handsize) then
  413.             begin
  414.                 b := true;
  415.                 l := 0;
  416.                 while b do
  417.                     begin
  418.                         if (p^ = $0D) or (n > handsize) then
  419.                             b := false
  420.                         else
  421.                             begin
  422.                                 c := chr(p^);
  423.                                 l := l + 1;
  424.                                 thestr[l] := c;
  425.                             end;
  426.                         n := n + 1;
  427.                         p := pointer(ord4(thehndl^) + n);
  428.                     end;
  429. {turn it into a str255}
  430.                 MCSetStrLen(thestr, l);
  431.             end;
  432. {and return whatever thestr is}
  433.         MCGetStrLineXFromHndl := thestr;
  434.     end;
  435.  
  436.     function MCGetNumberOfItemsInStr;
  437. {could rewrite using Munger or similar to search for returns..etc}
  438.         var
  439.             i: integer;
  440.             count: integer;
  441.     begin
  442.         i := 0;
  443.         count := 0;
  444.         while i <= length(thestr) do
  445.             begin
  446.                 i := i + 1;
  447.                 if thestr[i] = delimiter then
  448.                     count := count + 1;
  449.             end;
  450. {if last character is not a delim, then there was one more item after last delimiter}
  451.         if thestr[i] <> delimiter then
  452.             MCGetNumberOfItemsInStr := count + 1; {for the last item}
  453.     end;
  454.  
  455.     function MCGetStrItemXFromStr;
  456.         var
  457.             i, count: integer;
  458.             newstr: Str255;
  459.     begin
  460.         newstr := thestr;
  461.         count := 0;
  462.         while count < itemx - 1 do
  463.             begin
  464.                 i := pos(delimiter, newstr);
  465.                 if i <> 0 then
  466.                     delete(newstr, 0, i + 1)
  467.                 else {can't find enough items}
  468.                     newstr := '';
  469.                 count := count + 1;
  470.             end;
  471.         i := pos(delimiter, newstr);
  472.         if i <> 0 then
  473.             delete(newstr, i, length(newstr) - i + 1);
  474.         MCGetStrItemXFromStr := newstr;
  475.     end;
  476.  
  477.  
  478.  
  479. {-------------------------------------------------------------------}
  480.  
  481.     function MCGetStrItemXFromHndl (thehndl: Handle;
  482.                                     itemx: longint;
  483.                                     delimiter: char): str255;
  484.         var
  485.             count: longint;
  486.             p: ptr;
  487.             dels, newstr: Str255;
  488.             offset, charstocopy, hlen: longint;
  489.             n: longint;
  490.     begin
  491. {find offset of item}
  492.         if thehndl = nil then
  493.             begin
  494.                 MCGetStrItemXFromHndl := '';
  495.                 exit(MCGetStrItemXFromHndl);
  496.             end;
  497.         HLock(theHndl);
  498.         count := 0;
  499.         dels := delimiter;
  500.         offset := -1;
  501.         hlen := GetHandleSize(thehndl);
  502.         while count < itemx - 1 do
  503.             begin
  504.                 offset := offset + 1;
  505.                 offset := Munger(thehndl, offset, @dels[1], 1, nil, 0); {find next delimchar}
  506.                 if offset <= 0 then {delimchar 1 not found, line number does not exist}
  507.                     begin
  508.                         if hlen > 255 then
  509.                             hlen := 255;
  510.                         BlockMove(thehndl^, @newstr[1], hlen);
  511.                         MCSetStrLen(newstr, hlen);
  512.                         MCGetStrItemXFromHndl := newstr;
  513.                         HUnlock(theHndl);
  514.                         exit(MCGetStrItemXFromHndl);
  515.                     end
  516.                 else
  517.                     count := count + 1;
  518.             end;
  519.  
  520.         n := offset + 1;
  521.         p := Pointer(ord4(thehndl^) + n); {point p at the next character after the found return}
  522.         offset := Munger(thehndl, offset + 1, @dels[1], 1, nil, 0); {find next delimchar}
  523.         if offset <= 0 then
  524.             offset := hlen;
  525.  
  526. {copy the item}
  527.         charstocopy := offset - n;
  528.         if charstocopy > 255 then
  529.             charstocopy := 255;
  530.         BlockMove(p, @newstr[1], charstocopy); {copy the diff into the string}
  531.         if MemError <> noErr then
  532.             MCGetStrItemXFromHndl := ''
  533.         else
  534.             begin
  535.                 MCSetStrLen(newstr, charstocopy);
  536.                 MCGetStrItemXFromHndl := newstr;
  537.             end;
  538.         Hunlock(thehndl);
  539.     end;
  540.  
  541. {copies everything following the offset to the next occurrence of the delimiter}
  542. {use this function}
  543.     function MCGetStrItemOffsetFromHndl (thehndl: Handle;
  544.                                     delim: char;
  545.                                     var offset: longint {offset to copy from}
  546.                                     ): Str255;
  547.         var
  548.             dels: Str32;
  549.             endoff, len: longint;
  550.             tmpstr: Str255;
  551.     begin
  552.         dels := delim;
  553.         endoff := Munger(thehndl, offset, @dels[1], 1, nil, 0);
  554.         if endoff <= 0 then
  555.             begin
  556.                 endoff := GetHandleSize(thehndl);
  557.                 if offset >= endoff then
  558.                     begin
  559.                         MCGetStrItemOffsetFromHndl := '';
  560.                         exit(MCGetStrItemOffsetFromHndl);
  561.                     end;
  562.             end;
  563.         len := endoff - offset;
  564.         if len > 255 then
  565.             len := 255;
  566.         BlockMove(ptr(ord4(thehndl^) + offset), @tmpstr[1], len);
  567.         MCSetStrLen(tmpstr, len);
  568.         MCGetStrItemOffsetFromHndl := tmpstr;
  569.         offset := offset + len;
  570.     end;
  571.  
  572.     function MCGetNextStrLineFromHndl (thehndl: handle;
  573.                                     var offset: longint): Str255;
  574. {starts looking from an offset passed to the function, which then contains where the search left off last time}
  575. {to search sequentially along a handle from start, pass 0 as the initial value for offset, and }
  576. {keep calling with same value in a loop}
  577. {should really rewrite some of these functions using BlockMove. Have to find out how to do it!}
  578.         var
  579.             b: boolean;
  580.             count: longint;
  581.             p, q: ptr;
  582.             finalhandle: Handle;
  583.             c: char;
  584.             err: OSErr;
  585.             l: integer;
  586.             handsize: longint;
  587.             tmpstr: str255;
  588.     begin
  589. {move pointer to start of line x of handle}
  590.         handsize := GetHandleSize(thehndl) - 1;{remember to crop off the EOF if reading from a file}
  591.         finalhandle := NewHandle(0);
  592.         b := true;
  593.         p := nil;
  594.  
  595.         p := pointer(ord4(thehndl^) + offset);{p should now be pointing where we left off}
  596.         offset := offset + 1;{first char of line}
  597.  
  598. {copy until hit another return or a zero into a string}
  599.         if (p^ <> 0) and (offset <= handsize) then
  600.             begin
  601.                 b := true;
  602.                 l := 0;
  603.                 count := 1;
  604.                 while b and (count < 255) do
  605.                     begin
  606.                         if (p^ = $0D) or (p^ = 0) then
  607.                             b := false
  608.                         else
  609.                             begin
  610.                                 c := chr(p^);
  611.                                 tmpstr[count] := c;
  612.                                 count := count + 1;
  613.                             end;
  614.                         p := pointer(ord4(thehndl^) + offset);
  615.                         offset := offset + 1;
  616.                     end;
  617.                 offset := offset - 1;
  618.                 MCSetStrLen(tmpstr, count - 1);
  619.                 MCGetNextStrLineFromHndl := tmpstr;
  620.             end
  621.         else if offset = handsize then
  622.             MCGetNextStrLineFromHndl := '';
  623.     end;
  624.  
  625.     function MCAppendStrToHndl;
  626.     begin
  627.         MCAppendStrToHndl := noErr;
  628.         if str = '' then
  629.             exit(MCAppendStrToHndl);
  630.         if h = nil then
  631.             h := NewHandle(0);
  632.         MCAppendStrToHndl := PtrAndHand(POINTER(ORD4(@str) + 1), h, LENGTH(str));
  633.     end;
  634.  
  635.     function MCAppendPtrToHndl;
  636.     begin
  637.         MCAppendPtrToHndl := noErr;
  638.         if p = nil then
  639.             exit(MCAppendPtrToHndl);
  640.         if h = nil then
  641.             h := NewHandle(0);
  642.         MCAppendPtrToHndl := PtrAndHand(p, h, len);
  643.     end;
  644.  
  645.     function MCAppendReturnToHndl;
  646.         var
  647.             s: str255;
  648.     begin
  649.         MCAppendReturnToHndl := noErr;
  650.         if h = nil then
  651.             h := NewHandle(0);
  652.         s := chr($0D);
  653.         MCAppendReturnToHndl := PtrAndHand(POINTER(ORD4(@s) + 1), h, LENGTH(s));
  654.     end;
  655.  
  656.     function MCAppendHndlToHndl;
  657. {appends handle fromh after handle toh}
  658.         var
  659.             len: longint;
  660.             myerr: OSErr;
  661.     begin
  662.         MCAppendHndlToHndl := noErr;
  663.         if toh = nil then
  664.             toh := NewHandle(0);
  665.         if fromh = nil then
  666.             exit(MCAppendHndlToHndl);
  667.         MCAppendHndlToHndl := HandAndHand(fromh, toh);
  668.     end;
  669.  
  670.     function MCHPascalToZero;
  671. {converts a pascal string to hypercard (null-terminated) string without using paramptr}
  672.         var
  673.             myErr: OSErr;
  674.             strHdl: Handle;
  675.     begin
  676.         strHdl := nil;
  677.         myErr := MCAppendStrToHndl(concat(str, chr(0)), strHdl);
  678.         if (myErr = noErr) and (strHdl <> nil) then
  679.             MCHPascalToZero := strHdl
  680.         else
  681.             MCHPascalToZero := nil;
  682.     end;
  683.  
  684.     function MCHZeroToPascal;
  685. {converts a hypercard(null-terminated) string to pascal string without using paramptr}
  686. {copes if it doesn't actually have a zero on the end}
  687.         var
  688.             n: integer;
  689.             size: integer;
  690.             s1: Str255;
  691.             offset: longint;
  692.     begin
  693.         size := 0;
  694.         offset := -1;
  695.         s1 := chr(0);
  696.         if (strhdl = nil) then {old stuff fucked up if used a fake handle}
  697.             begin
  698.                 MCHZeroToPascal := '';
  699.                 exit(MCHZeroToPascal);
  700.             end;
  701. { find the nil}
  702.         offset := Munger(strhdl, 0, pointer(ord4(@s1[1])), 1, nil, 0);
  703.         if (offset < 0) then {not a hypercard handle, but we can cope nonetheless}
  704.             offset := GetHandleSize(strhdl);
  705.         if offset > 255 then
  706.             size := 255
  707.         else
  708.             size := offset;
  709.         if (size = 0) then
  710.             begin
  711.                 MCHZeroToPascal := '';
  712.                 exit(MCHZeroToPascal);
  713.             end;
  714.         MCSetStrLen(s1, size);
  715.         BlockMove(strhdl^, Pointer(ord4(@s1[1])), size);
  716.         MCHZeroToPascal := s1;
  717.     end;
  718.  
  719.     function MCNumberOfLinesInZero;
  720.         var
  721.             b: boolean;
  722.             n: integer;
  723.             p: ptr;
  724.             count: integer;
  725.     begin
  726. {intialize}
  727.         b := true;
  728.         p := nil;
  729.         n := 0;
  730.         count := 0;
  731.         while b do
  732.             begin
  733.                 p := pointer(ord4(thestr^) + n);
  734.                 n := n + 1;
  735.                 if (p^ = $0D) then
  736.  {$0D is return}
  737.                     count := count + 1;
  738.                 if p^ = 0 then
  739.                     b := false;
  740.             end;
  741.         MCNumberOfLinesInZero := count;
  742.     end;
  743.  
  744.     function MCGetStrLineXFromZero;
  745.         var
  746.             b: boolean;
  747.             n, count: integer;
  748.             p, q: ptr;
  749.             thestr: str255;
  750.             c: char;
  751.             err: OSErr;
  752.             l: integer;
  753.     begin
  754. {move pointer to start of line x of string}
  755.         b := true;
  756.         p := nil;
  757.         n := 0;
  758.         count := 0;
  759.         while b do
  760.             begin
  761.                 p := pointer(ord4(thehndl^) + n);
  762.                 n := n + 1;
  763.                 if count = lineno - 1 then
  764.                     b := false;
  765.                 if (p^ = $0D) then
  766.                     count := count + 1;
  767.                 if p^ = 0 then
  768.                     b := false;
  769.             end;
  770.  
  771. {copy until hit another return or a zero into a string}
  772.         if p^ <> 0 then
  773.             begin
  774.                 b := true;
  775.                 l := 0;
  776.                 while b do
  777.                     begin
  778.                         if (p^ = $0D) or (p^ = 0) then
  779.                             b := false
  780.                         else
  781.                             begin
  782.                                 c := chr(p^);
  783.                                 l := l + 1;
  784.                                 thestr[l] := c;
  785.                             end;
  786.                         p := pointer(ord4(thehndl^) + n);
  787.                         n := n + 1;
  788.                     end;
  789. {turn it into a str255}
  790.                 MCSetStrLen(thestr, l);
  791.                 MCGetStrLineXFromZero := thestr;
  792.             end;
  793.     end;
  794.  
  795. end.